/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package selfsignedx509certificategeneratordemo;

/**
 *
 * @author rmartinezch
 */
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Date;

import javax.security.auth.x500.X500Principal;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.x509.X509V1CertificateGenerator;

//http://www.java2s.com/Code/JarDownload/guava/guava.jar.zip
import com.google.common.base.Strings;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.CertificateException;

/**
 * Demo of a generation of a X509 Self Signed Certificate using <a
 * href="http://www.bouncycastle.org/">Bouncy Castle</a> library.
 */
public class SelfSignedX509CertificateGeneratorDemo {

    static {
        // añadiendo el proveedor Bouncy castle al paquete java.security.Security
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * <p>
     * Generate a self signed X509 certificate .
     * </p>
     * <p>
     * TODO : do the same with
     * {@link org.bouncycastle.cert.X509v1CertificateBuilder} instead of the
     * deprecated {@link org.bouncycastle.x509.X509V1CertificateGenerator}.
     * </p>
     */
    @SuppressWarnings("deprecation")
    static void generateSelfSignedX509Certificate() throws NoSuchAlgorithmException, NoSuchProviderException, CertificateEncodingException,
            SignatureException, InvalidKeyException, IOException, KeyStoreException, CertificateException {

        // Fecha inicial - ayer
        Date validityBeginDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
        // Fecha final - dentro de dos años
        Date validityEndDate = new Date(System.currentTimeMillis() + 2 * 365 * 24 * 60 * 60 * 1000);

        // Instancia "RSA" public-key cryptography algorithm
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
        // tamaño de las claves
        keyPairGenerator.initialize(2048, new SecureRandom());
        // Generar el par de claves
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // Instancia del certificado X509
        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
        // metada
        X500Principal dnName = new X500Principal("CN=Ronald Martinez");
        // número de serie
        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
        // titular
        certGen.setSubjectDN(dnName);
        // emisor
        certGen.setIssuerDN(dnName); // use the same
        // inicio de validez
        certGen.setNotBefore(validityBeginDate);
        // fin de validez
        certGen.setNotAfter(validityEndDate);
        // clave pública del certificado
        certGen.setPublicKey(keyPair.getPublic());
        // algoritmo de firma
        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");

        X509Certificate cert = certGen.generate(keyPair.getPrivate(), "BC");

        // DUMP CERTIFICATE AND KEY PAIR
        System.out.println(Strings.repeat("=", 80));
        System.out.println("Certificado");
        System.out.println(Strings.repeat("=", 80));
        System.out.println();
        System.out.println(cert);
        System.out.println();

        System.out.println(Strings.repeat("=", 80));
        System.out.println("Certificado PEM (para almacenar en un archivo rm.pem)");
        System.out.println(Strings.repeat("=", 80));
        System.out.println();
        PEMWriter pemWriter = new PEMWriter(new PrintWriter(System.out));
        pemWriter.writeObject(cert);
        pemWriter.flush();
        System.out.println();

        System.out.println(Strings.repeat("=", 80));
        System.out.println("clave privada PEM (para almacenar en un archivo priv-rm.pem)");
        System.out.println(Strings.repeat("=", 80));
        System.out.println();
        pemWriter.writeObject(keyPair.getPrivate());
        pemWriter.flush();
        System.out.println();
        
        System.out.println(Strings.repeat("=", 80));
        System.out.println("guardar el certificado en un archivo de disco");
        System.out.println(Strings.repeat("=", 80));
        String cerName = "RM-cert.cer";
        String cerPath = "D:/Data/";
        FileOutputStream fos = new FileOutputStream(cerPath + cerName);  
        fos.write(cert.getEncoded());  
        fos.close();
        
        /*
        KeyStore privateKS = KeyStore.getInstance("JKS");  
        FileInputStream fis = new FileInputStream(cerPath + cerName);  
        privateKS.load(fis, "keyStorePass".toCharArray());
        */
    }

    public static void main(String[] args) {
        try {
            generateSelfSignedX509Certificate();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}